class Animal(object):
    def run(self):
        print('Animal is running...')

class Dog(Animal):
    def run(self):
        print('Dog is running...')

class Cat(Animal):
    def run(self):
        print('Cat is running...')


def run_twice(animal):
    animal.run()
    animal.run()


a = Animal()
d = Dog()
c = Cat()

print('a is Animal?', isinstance(a, Animal))
print('a is Dog?', isinstance(a, Dog))
print('a is Cat?', isinstance(a, Cat))


print('d is Animal?', isinstance(d, Animal))
print('d is Dog?', isinstance(d, Dog))
print('d is Cat?', isinstance(d, Cat))

run_twice(c)

# run_twice(animal)其实就是一个接口函数，可以用来接收一个对象，
# 不管什么类型的对象都能接受，并且只要这个对象有run()都可以输出。
# 作者想表达的意思应该是多态，如果传进去的对象自身没有定义run()，
# 就会调用基类的run()，如果子对象有run()，就会调用自身的run()，
# 也就实现了多态。但是所说的鸭子什么的，也就是只要传进去的是一个对象，
# 并且该对象有run()，就可以体现出run()的特性。

# 对于Python这样的动态语言来说，则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了：
class Timer(object):
    def run(self):
        print('Start ....')


run_twice(Timer())


# 继承可以把父类的所有功能都直接拿过来，这样就不必重零做起，
# 子类只需要新增自己特有的方法，也可以把父类不适合的方法覆盖重写


# 动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的。


print(type(a))
